home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / INFO / DOSTIPS1.ZIP / DOSDEBUG.TXT < prev    next >
Text File  |  1985-11-24  |  17KB  |  303 lines

  1.                       DEBUG As An Assembler
  2.               (PC World January 1985 Star-Dot-Star)
  3.  
  4.      ...take advantage of the DOS 2.x I/O redirection facility to 
  5. mimic the operations of a conventional assembler.  Use your word 
  6. processing program to create a file that contains the commands 
  7. and instructions shown in CTTYFIX.ASM (making sure that the file 
  8. ends with DEBUG's Quit command).  Then type:
  9.           DEBUG < CTTYFIX.ASM > CTTYFIX.LST
  10. and DEBUG assembles the file into a .COM file and creates an .LST 
  11. file similar to that generated by an assembler.
  12.      Files can contain assembly language pseudo-ops such as DB 
  13. for defining bytes and semicolons for making comments.  Note that, 
  14. thanks to this use of the redirection facility, you can edit a 
  15. file and reassemble it if there are any errors.
  16.      Another use of I/O redirection with DEBUG is to create an 
  17. assembly language file (of sorts) from .COM and .EXE files.  The 
  18. key is to use the Unassemble command while the output is
  19. redirected to a disk file, then edit the file to remove extraneous 
  20. data such as the segment address and offset that precedes each 
  21. line of code.  The resulting file can be commented using
  22. semicolons, edited, and then reassembled using DEBUG's assembler.
  23.  
  24. -----------------------------------------------------------------
  25.                         New DEBUG Command
  26.               (PC World January 1985 Star-Dot-Star)
  27.  
  28.      Adding the routine below in DEBUGMOD to the DOS 2.x version 
  29. of DEBUG.COM allows the program to list cross-references for Jump 
  30. and Call instructions.  The format for the new command is X range 
  31. value, where range is the usual "segment:offset offset" or
  32. "segment:offset L value" style used under DEBUG, and value is a
  33. number between zero and 0FFFFh that represents an address.  When 
  34. executed, all the Jumps and Calls referencing that address will 
  35. be displayed.  The program does not work properly with .EXE files. 
  36. For this reason, use a name other than DEBUG.COM so you can have 
  37. both versions available.
  38. - - - - -
  39. DEBUGMOD
  40.  
  41. A>DEBUG DEBUG.COM
  42. -A 2E80
  43. xxxx:2E80 CALL      03AD
  44. xxxx:2E83 PUSH      CX
  45. xxxx:2E84 PUSH      AX
  46. xxxx:2E85 PUSH      DX
  47. xxxx:2E86 MOV       CX,0004
  48. xxxx:2E89 CALL      051C
  49. xxxx:2E8C POP       DI
  50. xxxx:2E8D POP       ES
  51. xxxx:2E8E POP       CX
  52. xxxx:2E8F MOV       SI,2D3F
  53. xxxx:2E92 MOV       AX,E9E8
  54. xxxx:2E95 MOV       [SI],AX
  55. xxxx:2E97 PUSH      CX
  56. xxxx:2E98 PUSH      DI
  57. xxxx:2E99 LODSB
  58. xxxx:2E9A SCASB
  59. xxxx:2E9B LOOPNZ    2E9A
  60. xxxx:2E9D JNZ       2EBB
  61. xxxx:2E9F PUSH      DI
  62. xxxx:2EA0 MOV       BX[DI]
  63. xxxx:2EA2 DEC       DI
  64. xxxx:2EA3 ADD       WORD PTR BX,03
  65. xxxx:2EA6 ADD       BX,DI
  66. xxxx:2EA8 CMP       BX,DX
  67. xxxx:2EAA JNZ       2EB6
  68. xxxx:2EAC PUSH      DX
  69. xxxx:2EAD PUSH      AX
  70. xxxx:2EAE CALL      0318
  71. xxxx:2EB1 CALL      02B3
  72. xxxx:2EB4 POP       AX
  73. xxxx:2EB5 POP       DX
  74. xxxx:2EB6 POP       DI
  75. xxxx:2EB7 JCXZ      2EBB
  76. xxxx:2EB9 JMP       2E9A
  77. xxxx:2EBB CMP       SI,2D41
  78. xxxx:2EBF POP       DI
  79. xxxx:2EC0 POP       CX
  80. xxxx:2EC1 JNZ       2E97
  81. xxxx:2EC3 RET
  82. xxxx:2EC4
  83. -E 0396 80 2E
  84. -N D.COM
  85. -W
  86. Writing 2E80 bytes
  87. -Q
  88. A>
  89.  
  90. -----------------------------------------------------------------
  91.                 Simple Assembling with IBM DEBUG
  92.          (COMPUTE! Magazine November 1985 by T. Victor)
  93.  
  94.      DEBUG includes a miniassembler, which converts assembly language
  95. instructions into machine language (ML) directly in memory, and a
  96. disassembler, which allows you to revers this process and examine ML
  97. programs already in memory.  DEBUG also has trace and breakpoint
  98. functions for testing ML programs, utilities for loading and saving
  99. programs on disk, and several other valuable features.  You can write
  100. small ML programs with DEBUG.
  101.      Load DEBUG to get its hyphen prompt.  You can return to DOS at
  102. any time by putting a DOS disk back in the drive, typing Q for Quit,
  103. and pressing Enter.
  104.      Let's ask DEBUG to copy itself onto another disk.  You could use
  105. the DOS COPY command, but using DEBUG is a good way to learn how to
  106. load and save ML program files.
  107.      DEBUG has three commands for disk operations: L (Load), W (Write),
  108. and N (Name).  N creates a data structure called a file control block
  109. (FCB) that DOS uses for all disk operations, including DEBUG's Load
  110. and Write.  The FCB contains the name of a file, along with information
  111. such as size and file organization.
  112.      The first step in backing up DEBUG is to load another copy of it
  113. into memory.  Type N DEBUG.COM and press Enter.  DEBUG responds with
  114. another hyphen.  Next, type L and press Enter.  This loads a second
  115. copy of DEBUG.
  116.      Remove the DEBUG disk and replace it with a formatted disk that
  117. you'll be using for ML programs.  Type W and press Enter.  DEBUG
  118. displays the message "Writing 2E80 bytes".  You now have a copy of
  119. DEBUG.COM on your ML disk.
  120.      Let's try assembling a program with DEBUG.  Start by typing A 100
  121. to start assembling at address 100h.  (All input and output with DEBUG
  122. is expressed in hexadecimal.)  DEBUG responds with xxxx:0100, where
  123. xxxx is a four-digit hexadecimal number.  This number is the current
  124. value of the code segment register.
  125.      Now type in the following program.  DEBUG displays the memory
  126. address of each instructino for you.  All you need to enter are the
  127. instructions.
  128.           MOV AH,09
  129.           MOV DX,109
  130.           INT 21
  131.           INT 20
  132.           DB "HELLO THERE$"
  133.      Press Enter to leave the assembler.  This program is the ML
  134. equivalent of everyone's first BASIC program:  10 PRINT "HELLO THERE".
  135.      The ML version looks quite a bit longer, but it would be even more
  136. involved if it weren't for the INT 21h instruction, which calls a DOS
  137. function routine (Print String) by executing a software INTerrupt.
  138. Before calling this routine, the program takes two preparatory actions.
  139. The first instruction loads the AH register with the value 9.  In 8088
  140. machine language, instructions with two operands like MOV AH,09 operate
  141. from right to left -- just as A = 9 in BASIC moves the value 9 into the
  142. variable A.  You specify the destination operand first, then the source
  143. operand.
  144.      AH is the high (most significant) byte of AX, the 16-bit (two-
  145. byte) accumulator register of the 8088.  When a program calls Interrupt
  146. 21h, the value in AH indicates the function you're asking DOS to
  147. perform.  Function 9, Print String, displays a string on the screen,
  148. starting with the character at the address contained in the DX register
  149. and ending with the character $.  The second instruction moves the
  150. address 109h into the DX register.  The last instruction, INT 20h, ends
  151. the program by returning control to the program that called it -- in
  152. this case, DEBUG.
  153.      Finally, we create the string we want to pring using DB, a pseudo-
  154. opcode (pseudo-op).  When the assembler sees a pseudo-op such as DB, it
  155. performs a function instead of generating code.  This particular
  156. psueod-op tells the assembler to store bytes of data in memory,
  157. beginning at the current location.  The data can be either a list of
  158. hexadecimal numbers between 00 and FF, separated by spaces or commas,
  159. or a quoted string, as shown above.  If the data is a string, the ASCII
  160. code for each character is entered in memory.  The dollar sign at the
  161. end of the string is very important.  Without this delimiter, the Print
  162. String function will keep printing whatever bytes it happens to find in
  163. memory following the message.  It might be a long time before it comes
  164. across a $ and stops.
  165.      Now that the program is in memory, we can use the disassembler to
  166. examine it.  Type U for Unassemble, and DEBUG displays several rows of
  167. text on the screen (the number of rows differs between 40- and 80-
  168. column displays).  Notice that the disassembled code is aligned in four
  169. columns.  The first column shows the address of each instruction as two
  170. four-digit hexadecimal numbers separated by a colon, just as was
  171. displayed when you entered the program.  The first four-digit number is
  172. the current value of the code segment register mentioned before, and
  173. the second is the value of the instruction pointer.  To understand why
  174. two registers are needed to point to a single memory location requires
  175. some understanding of the 8088's addressing scheme.
  176.      The 8088 microprocessor can access up to one megabyte (1024K) of
  177. memory using 20-bit addresses.  However, for compatibility with older
  178. Intel processors, the 8088 has only a 16-bit instruction pointer.
  179. Because a 16-bit (four hexadecimal digit) register can only have values
  180. between 0 and 65,535, another register, the code segment register, is
  181. needed to address the entire 1,048,576 bytes allowed by the 8088.  The
  182. code segment register is also a 16-bit register, but instead of
  183. addressing individual bytes, it points to blocks of 16 bytes, called
  184. paragraphs.  Any five-digit hexadecimal address that ends in a zero is
  185. the beginning of a paragraph.  For example, the byte of memory at
  186. 5D320h is at the beginning of the paragraph addressed by a segment
  187. register containing 5D32h.
  188.      The code segment register points to the first paragraph of a 64K
  189. block of memory called the code segment (CS).  There are three other
  190. segments, the data segment (DS), stack segment (SS), and extra segment
  191. (ES), plus a register that points to the beginning of each.  In simple
  192. programs, however, all the segment registers usually have the same
  193. value as CS.  To find the next byte of code to be fetched, the value
  194. in the instruction pointer is added to the address of the beginning of
  195. the code segment.  The physical address of this byte can be found with
  196. this formula:  Physical Address = IP + (CS*16).
  197.      The effect of organizing memory this way is that a programmer
  198. doesn't have to know where the program will be loaded.  When DOS loads
  199. a .COM program, it starts the code segment at the beginning of any
  200. available paragraph in memory.  The program is loaded at an offset of
  201. 100h bytes above the start of the segment and the instruction pointer
  202. is set to 100h.  The four segment registers, CS, DS, SS and ES, all
  203. point to the start of the code segment.
  204.      The second instruction of the example program moves an address,
  205. 109h, into DX.  This address is an offset into the current data segment.
  206. The string to be printed is located at an offset of 109h only if the
  207. data segment is equal to the code segment register and the program
  208. starts at offset 100h.  In practice, the CS register is rarely changed
  209. except by DOS and needs little or no attention in most programs.
  210.      The second column of the disassembled listing on the screen
  211. contains four- or six-digit hexadecimal numbers.  These are the
  212. contents of the memory locations, the binary code which the 8088 can
  213. execute.  Notice that the first MOV instruction is one byte shorter
  214. than the second.  The first instruction only loads half of a 16-bit
  215. register (AH is the upper half of AX), so the data occupies one byte,
  216. but the second MOV loads all of DX, which takes two bytes of data
  217. (a word).
  218.      The third column shows the mnemonics -- symbolic names for each
  219. opcode instruction.  The fourth column displays the operands.  This
  220. program consists of four opcodes: two MOV instructions followed by two
  221. INT instruction.  Notice that the DB pseudo-op doesn't show up in a
  222. disassembly.  Instead of displaying your characters, DEBUG tries to
  223. convert the string into assembly mnemonics, and therefore prints
  224. several meaningless instructions.  DEBUG is frequently fooled this way
  225. because program instructions and data are both stored as binary bytes.
  226. DEBUG has no way of knowing where the program ends and the data begins.
  227.      If you type another U, DEBUG continues to disassemble and display
  228. the next 16 or 32 bytes in memory (depending on your screen width).
  229. Since the program is only 21 bytes long, DEBUG starts displaying part
  230. of itself, still in memory from when you copied it.  Type U 100 to
  231. disassemble from the beginning of your program again.  DEBUG's U
  232. command also accepts both starting and ending addresses if you separate
  233. them by a space.
  234.      Save your program on disk before running it.  If the program
  235. causes something unexpected, like an infinite loop or a complete system
  236. crash, it's nice to have a copy saved.  Then you can load it and search
  237. for the error without typing the program again from scratch.
  238.      As before, you need to tell DEBUG the name of your file.  Type N
  239. HELLO.COM.  Now there's one more thing to consider: How many bytes of
  240. memory should DEBUG write to disk?  When we used the W command to copy
  241. DEBUG, it wrote the same number of bytes that it had loaded, but now
  242. we're saving a new program which has never been loaded.  When DEBUG
  243. loads a file, it stores the size of the file in the CX register and the
  244. four least significant bits of the BX register.  The same registers are
  245. used when DEBUG writes a file.  So if your program is less that 65,536
  246. bytes long, the BX register should be set to zero.
  247.      To examine and change CX, type R CX.  DEBUG prints the contents of
  248. CX (probably 2E80h), left over from copying DEBUG), then prints a colon
  249. at the beginning of the next line.  You can press Enter to leave the
  250. value unchanged, or type a new value.  Since the new program is 21
  251. bytes long, type 15 (the hexadecimal equivalent of 21) and press Enter.
  252. Now type W to write the program to disk.  DEBUG responds with the
  253. message "Writing 0015 bytes," then returns the prompt.
  254.      Now that your program is safe on disk, run it by typing G and
  255. pressing Enter.  The screen should display HELLO THERE.  Then DEBUG
  256. prints "Program completed normally" followed by its usual prompt.  If
  257. your program completed but didn't print correctly, disassemble starting
  258. from 100h and check that all instruction are correct.  If your program
  259. locked up the computer, reboot, restart DEBUG, and thank yourself for
  260. saving the program.  Reload the program with N and L, then disassemble
  261. it to see what it looks like.  If you don't know what's wrong, one
  262. technique is to try setting a breakpoint.  This halts the program at a
  263. predetermined point so you can check the contents of the registers.
  264.      For instance, to make the program stop before the INT 20h
  265. instruction, you can set one or more breakpoints.  To set a breakpoint,
  266. type G followed by the addresses of one or more instructions in your
  267. program.  If you set more than one breakpoint, separate the addresses
  268. with spaces.  The program begins executing, but stops when the
  269. instruction pointer equals the address of a breakpoint.  DEBUG displays
  270. the contents of all registers and flags and disassembles the
  271. instruction at the breakpoint (the instruction pointer, the next
  272. instruction to be executed).  Type G to restart the program at the
  273. instruction that the instruction pointer references.
  274.      If you stopped your program with a breakpoint but want to restart
  275. it from the beginning, type G=100.  DEBUG sets the instruction pointer
  276. to 100h (or whatever address you specify) before starting.  You can
  277. also set both the starting address and one or more breakpoints.  Just
  278. include the breakpoint addresses on the same command line, separating
  279. them from the starting address and each other with spaces.
  280.      Keep this in mind: Before DEBUG executes a G command, it saves the
  281. values of all the registers, including the instruction pointer.  If the
  282. program runs normally, and completes by executing INT 20h, DEBUG 
  283. restores all the registers.  This is great if your program runs all the
  284. way from the beginning to end.  You just type G and your program runs
  285. again.  If, however, your programs has just completed after being
  286. restarted from a breakpoint, the instruction pointer now points to the
  287. location where the breakpoint was set.  Typing G starts it from the
  288. breakpoint again.  To run the program from the beginning, type G=100.
  289.      Some other useful DEBUG commands are D (Dump), which displays the
  290. contents of a block of memory as hexadecimal numbers and ASCII
  291. characters; E (Enter), to examine and change the contents of individual
  292. memory locations; and T (Trace), which executes an ML program one
  293. instruction at a time, displaying all registers and flags between
  294. instructions.
  295.      You'll find DEBUG a big help in testing your programs.  Though you
  296. might use a separate assembler when your programs get larger, DEBUG
  297. remains useful for testing and modifying the assembled programs.  If
  298. you want to know more, there is a complete description of each DEBUG
  299. command in Chapter 12 of the DOS 2.00 Manual and Chapter 8 of the DOS
  300. 2.10 Manual.  Information on the DOS functions and interrupts can be
  301. found in Appendix D of the DOS 2.00 Manual and Chapter 5 of the DOS
  302. 2.10 Technical Reference Manual.
  303.